package com.apes.fn.scm.retailOrder.service.account.retail;

import com.apes.fn.scm.retailOrder.model.RetailOrder;
import com.apes.fn.scm.retailOrder.service.NoInventoryRetailItemsService;
import com.apes.fn.scm.retailOrder.service.account.BackBatchAndSupplierService;
import com.apes.fn.scm.retailOrder.service.account.RetailAccountData;
import com.apes.fn.server.servicePlan.model.ClientInvoiceRules;
import com.apes.fn.server.servicePlan.model.ClientInvoiceRulesItem;
import com.apes.fn.server.servicePlan.model.ServicePlan;
import com.apes.fn.server.servicePlan.model.ServicePlanItem;
import com.apes.fn.server.servicePlan.repository.ServicePlanItemRepository;
import com.apes.fn.server.servicePlan.repository.ServicePlanRepository;
import com.apes.fn.server.servicePlan.service.ClientInvoiceRulesService;
import com.apes.framework.api.SpringManager;
import com.apes.framework.util.Arith;
import com.apes.framework.util.MapUtil;
import com.apes.framework.util.ReflectUtil;
import com.apes.scm.account.account.model.AccountingMethod;
import com.apes.scm.account.account.model.InventoryMode;
import com.apes.scm.account.tax.model.Tax;
import com.apes.scm.account.tax.service.TaxService;
import com.apes.scm.masterdata.party.model.PartyRole;
import com.apes.scm.voucher.model.Voucher;
import com.apes.scm.voucher.model.VoucherInventory;
import com.apes.scm.voucher.model.VoucherItem;
import com.apes.scm.voucher.repository.VoucherInventoryRepository;
import com.apes.scm.voucher.service.BusinessType;
import com.apes.scm.voucher.service.VoucherType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 单位客户挂账部分的账目逻辑
 *
 * @author wuq
 * @Time 2023-3-21 16:12
 * @Description
 */
@RetailAccount(value = "unitClient", name = "单位客户挂账")
@Service
public class UnitClientVoucherService extends BackBatchAndSupplierService {

    @Autowired
    private NoInventoryRetailItemsService noInventoryRetailItemsService;
    @Autowired
    private ClientInvoiceRulesService clientInvoiceRulesService;
    @Autowired
    private VoucherInventoryRepository voucherInventoryRepository;
    @Autowired
    private TaxService taxService;

    @Override
    public void process(RetailAccountData retailAccountData) {
        RetailOrder retailOrder = retailAccountData.getRetailOrder();

        ServicePlan servicePlan = SpringManager.getBean(ServicePlanRepository.class).findOne(retailOrder.getSource());
        List<ServicePlanItem> unitClientPlanItems = servicePlan.getServicePlanItems().stream()
                .filter(servicePlanItem -> Objects.nonNull(servicePlanItem.getUnitClient()))
                .collect(Collectors.toList());
        if (unitClientPlanItems.size() == 0) return;

        // 查询单位客户挂账规则
        PartyRole unitClient = unitClientPlanItems.get(0).getUnitClient();
        ClientInvoiceRules clientInvoiceRule = clientInvoiceRulesService.findClientInvoiceRules(retailOrder.getDept(), unitClient);
        if (Objects.isNull(clientInvoiceRule))
            throw new RuntimeException("没有找到 (" + unitClient.getId() + ") " + unitClient.getName() + "的开票规则，请检查！");

        // 采购凭证
        noInventoryRetailItemsService.purchaseVoucher(retailOrder);

        // 判断是否为开票公司
        if (clientInvoiceRule.getCompany().getId().equals(retailOrder.getCompany().getId())) {
            // 为开票公司, 默认的比率为 1
            retailSaleVoucher(retailOrder, unitClient, 1d);
        } else {
            // 非开票公司
            crossSale(retailOrder, clientInvoiceRule);
        }
    }

    private void crossSale(RetailOrder retailOrder, ClientInvoiceRules clientInvoiceRule) {
        // 获取内部交易的比率
       List<ClientInvoiceRulesItem> rulesItems = clientInvoiceRule.getClientInvoiceRulesItems().stream()
                .filter(item -> item.getDept().getId().equals(retailOrder.getDept().getId()))
                .collect(Collectors.toList());
       double ratio = rulesItems.get(0).getCrossSingleRatio();

        // 门店销售给开票公司
        retailSaleVoucher(retailOrder, clientInvoiceRule.getCompany(), ratio);

        // 开票公司采购、销售
        Voucher crossPurchaseVoucher = createCrossPurchaseVoucher(retailOrder, clientInvoiceRule, ratio);

        // 对单位客户的销售
        createCrossSaleVoucher(crossPurchaseVoucher, clientInvoiceRule.getCustomer(), retailOrder);
    }

    /**
     * 直接对开票方开销售
     *
     * @param retailOrder 零售单
     * @param partner     单位客户
     */
    private void retailSaleVoucher(RetailOrder retailOrder, PartyRole partner, double ratio) {
        Voucher voucher = new Voucher();
        voucher.setBusinessType(BusinessType.SALE_ORDER);
        ReflectUtil.copy(retailOrder, voucher, "dept", "company", "scene", "clerk");

        voucher.setPartner(partner.getParty().getPatyRoleByType("Customer"));

        voucher.setInventoryMode(InventoryMode.IM_OWN);     //设置库存模式：自有
        voucher.setAccountingMethod(AccountingMethod.AM_PURCHASE);  // 核算方式：经销
        voucher.setCustomerExpand(retailOrder.getCustomerExpand().getId());

        voucher.setOrigin(retailOrder.getId());
        voucher.setOriginBusinessType(retailOrder.getInnerBusinessType());
        voucher.setSource(retailOrder.getId());
        voucher.setSourceBusinessType(retailOrder.getInnerBusinessType());
        voucher.setClassification(VoucherType.UNIT_CLIENT);

        voucher.setVoucherItems(
                retailOrder.getSaleItems().stream().map(
                        item -> {
                            VoucherItem voucherItem = new VoucherItem();

                            ReflectUtil.copy(item, voucherItem, "product", "uom", "supplier", "inventoryBatch");

                            voucherItem.setOwner(item.getOwner());
                            voucherItem.setOriginItemId(item.getId());
                            voucherItem.setSourceItemId(item.getId());

                            voucherItem.setProductQty(item.getProductUomQty());
                            voucherItem.setDiscount(item.getDiscountAmount());

                            // 通过比率计算单价
                            voucherItem.setPriceUnit(Arith.round(item.getPriceUnit() * ratio, 4));

                            Tax tax = taxService.getSaleTax(retailOrder.getCompany(), item.getProduct());
                            voucherItem.setTax(tax);

                            // 判断是否为工单内协
                            if (item.getProductRule() == 20) {
                                ServicePlanItem servicePlanItem = SpringManager.getBean(ServicePlanItemRepository.class).findById(item.getOriginnumber()).orElse(null);
                                if (servicePlanItem != null) {
                                    voucherItem.setSupplier(servicePlanItem.getSupplier());
                                    voucherItem.setInventoryBatch(servicePlanItem.getInventoryBatch());
                                }
                            }
                            return voucherItem;
                        }).collect(Collectors.toSet())
        );

        voucher = invoke("voucher.create", MapUtil.mapped(voucher));
        // 增加账单
        createInvoiceAndFixOriginNumber(retailOrder, voucher);
    }


    /**
     * 对门店的采购凭证
     *
     * @param retailOrder       零售单
     * @param clientInvoiceRule 开票规则
     * @return 采购凭证
     */
    private Voucher createCrossPurchaseVoucher(RetailOrder retailOrder, ClientInvoiceRules clientInvoiceRule, double ratio) {
        Voucher purVoucher = new Voucher();
        purVoucher.setBusinessType(BusinessType.PURCHASE_ORDER);
        purVoucher.setScene(retailOrder.getScene());

        purVoucher.setDept(clientInvoiceRule.getDept());
        PartyRole company = clientInvoiceRule.getCompany().getParty().getPartyRoleByType("Company");
        purVoucher.setCompany(company);
        purVoucher.setPartner(retailOrder.getCompany().getParty().getPatyRoleByType("Supplier"));

        purVoucher.setInventoryMode(InventoryMode.IM_OWN);     //设置库存模式：自有
        purVoucher.setAccountingMethod(AccountingMethod.AM_PURCHASE);  // 核算方式：经销

        purVoucher.setCustomerExpand(retailOrder.getCustomerExpand().getId());
        purVoucher.setClerk(retailOrder.getClerk()); //业务员
        purVoucher.setClassification(VoucherType.UNIT_CLIENT);

        purVoucher.setOrigin(retailOrder.getId());
        purVoucher.setOriginBusinessType(retailOrder.getInnerBusinessType());
        purVoucher.setSource(retailOrder.getId());
        purVoucher.setSourceBusinessType(retailOrder.getInnerBusinessType());

        PartyRole supplier = purVoucher.getPartner();
        purVoucher.setVoucherItems(
                retailOrder.getSaleItems().stream().map(
                        item -> {
                            VoucherItem voucherItem = new VoucherItem();
                            ReflectUtil.copy(item, voucherItem, "product", "uom");

                            voucherItem.setProductQty(item.getProductUomQty());
                            voucherItem.setOriginItemId(item.getId());
                            voucherItem.setSourceItemId(item.getId());
                            voucherItem.setOwner(company);
                            voucherItem.setDiscount(0d);

                            Tax tax = taxService.getPurchaseTax(company, supplier, item.getProduct());   //供应商进项税
                            voucherItem.setTax(tax);

                            // 通过比率计算单价
                            voucherItem.setPriceUnit(Arith.round(item.getPriceUnit() * ratio, 4));

                            return voucherItem;
                        }
                ).collect(Collectors.toSet()));

        purVoucher = invoke("voucher.create", MapUtil.mapped(purVoucher));

        changeFrostQty(purVoucher, "单位客户挂账，开票方对门店的采购凭证");

        //生成账单
        createInvoiceAndFixOriginNumber(retailOrder, purVoucher);
        return purVoucher;
    }


    private void createCrossSaleVoucher(Voucher purVoucher, PartyRole unitClient, RetailOrder retailOrder) {
        Voucher voucher = new Voucher();
        voucher.setBusinessType(BusinessType.SALE_ORDER);

        ReflectUtil.copy(purVoucher, voucher, "dept", "company", "clerk", "scene", "customerExpand");

        voucher.setPartner(unitClient.getParty().getPartyRoleByType("Customer"));

        voucher.setInventoryMode(InventoryMode.IM_OWN);     //设置库存模式：自有
        voucher.setAccountingMethod(AccountingMethod.AM_PURCHASE);  // 核算方式：经销
        voucher.setClassification(VoucherType.UNIT_CLIENT_CROSS);

        voucher.setSource(purVoucher.getId());
        voucher.setSourceBusinessType(purVoucher.getInnerBusinessType());
        voucher.setOrigin(retailOrder.getId());
        voucher.setOriginBusinessType(retailOrder.getInnerBusinessType());

        voucher.setVoucherItems(
                retailOrder.getSaleItems().stream().map(
                        item -> {
                            VoucherItem voucherItem = new VoucherItem();
                            ReflectUtil.copy(item, voucherItem, "product", "uom", "priceUnit");

                            voucherItem.setProductQty(item.getProductUomQty());

                            voucherItem.setOriginItemId(item.getOriginnumber());
                            voucherItem.setSourceItemId(String.valueOf(item.getId()));
                            voucherItem.setDiscount(0d);

                            Tax tax = taxService.getSaleTax(purVoucher.getCompany(), item.getProduct());
                            voucherItem.setTax(tax);

                            voucherItem.setOwner(purVoucher.getCompany());
                            return voucherItem;
                        }).collect(Collectors.toSet())
        );

        // 添加采购凭证批次以及供应商信息
        voucher.getVoucherItems().forEach(item -> {
            purVoucher.getVoucherItems().forEach(purchaseVoucherItem -> {

                VoucherInventory voucherInventory = voucherInventoryRepository.findByVoucherItem(purchaseVoucherItem).stream()
                        .findAny().orElseThrow(() -> new RuntimeException("找不到批次信息！"));

                if (item.getProduct().getId().equals(voucherInventory.getProduct().getId())) {
                    item.setInventoryBatch(voucherInventory.getInventoryBatch());
                    item.setSupplier(purchaseVoucherItem.getSupplier());
                }
            });
        });

        // 创建账单
        voucher = invoke("voucher.create", MapUtil.mapped(voucher));

        //增加账单
        createInvoiceAndFixOriginNumber(retailOrder, voucher);
    }
}
